using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Reflection;
using System.IO;
using System.Data.SqlClient;

namespace TST.SharePointObjects
{
    public class IndexerJobInstaller : SPFeatureReceiver
    {
        public const string INDEXERJOB_FEATURE_ID = "TST.SharePointObjects.IndexerJob";
        private const string SCHEDULESETTING = "TST.SharePointObjects.TimerJob.Schedule";
        private const string TIMESETTING = "TST.SharePointObjects.TimerJob.Time";

        /// <summary>
        /// Occurs after a Feature is installed.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }

        /// <summary>
        /// Occurs when a Feature is uninstalled.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }

        /// <summary>
        /// Occurs after a Feature is activated.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                RegisterBreadCrumbNodes();
                InstallTimerJob(properties);
                SetupDatabaseSecurity(properties);
            }
            catch (SqlException sqlEx)
            {
                TraceProvider.WriteError(string.Format("SQL Error installing SharePoint Objects timerjob: {0}.", sqlEx.Message), "IndexerJobInstaller.FeatureActivated");
                throw new Exception("Database error while installing the SharePoint Objects timer job. Most likely you do not have enough permissions in the SharePoint configuration database to install the timerjob. See the SharePoint diagnostics logs for more details.");
            }
            catch (Exception ex)
            {
                TraceProvider.WriteError(string.Format("Error installing SharePoint Objects timerjob: {0}.", ex.Message), "IndexerJobInstaller.FeatureActivated");
                throw ex;
            }
        }

        private void SetupDatabaseSecurity(SPFeatureReceiverProperties properties)
        {
            SharePointObjectsDatabase database = SharePointObjectsDatabase.GetDatabase();
            if (database==null)
            {
                throw new Exception("SharePoint Objects database not found. Check the deployment manual and setup the database.");
            }
            SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;
            database.GrantLogin(webApplication.ApplicationPool.Username);
            database.GrantReadWritePermissions(webApplication.ApplicationPool.Username);
        }

        private void RegisterBreadCrumbNodes()
        {
            SPFarm.Local.Services.GetValue<SPWebService>().ApplyApplicationContentToLocalServer();
        }

        private void InstallTimerJob(SPFeatureReceiverProperties properties)
        {
            //if (ValidateProperties(properties))
            //{
                SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;

                // make sure the job isn't already registered
                foreach (SPJobDefinition job in webApplication.JobDefinitions)
                {
                    if (job.Name == INDEXERJOB_FEATURE_ID)
                        job.Delete();
                }

                // install the job
                IndexerJob indexJob = new IndexerJob(INDEXERJOB_FEATURE_ID, webApplication);

                foreach (SPFeatureProperty featureProperty in properties.Feature.Properties)
                {
                    if ((!string.IsNullOrEmpty(featureProperty.Name)) && (!string.IsNullOrEmpty(featureProperty.Value)))
                    {
                        if (indexJob.Properties.ContainsKey(featureProperty.Name))
                        {
                            indexJob.Properties[featureProperty.Name] = featureProperty.Value;
                        }
                        else
                        {
                            indexJob.Properties.Add(featureProperty.Name, featureProperty.Value);
                        }
                    }
                }

                // Create the time
                int hour = 0;
                int minute = 0;
                string[] time = null;
                if (indexJob.Properties[TIMESETTING] != null)
                    time = indexJob.Properties[TIMESETTING].ToString().Split(new char[] { ':' });
                if (time != null)
                {
                    int.TryParse(time[0], out hour);
                    int.TryParse(time[1], out minute);
                }

                // Determine the Time Schema
                String schema = "day";
                if (indexJob.Properties[SCHEDULESETTING] != null)
                {
                    schema = indexJob.Properties[SCHEDULESETTING].ToString();
                }
                switch (schema.ToLower())
                {
                    default:
                    case "day":
                        SPDailySchedule scheduleDay = new SPDailySchedule();
                        scheduleDay.BeginHour = hour;
                        scheduleDay.BeginMinute = minute;
                        scheduleDay.BeginSecond = 0;
                        scheduleDay.EndHour = (scheduleDay.BeginHour + 1);
                        scheduleDay.EndMinute = 0;
                        scheduleDay.EndSecond = 0;
                        indexJob.Schedule = scheduleDay;
                        break;
                    case "week":
                        SPWeeklySchedule scheduleWeek = new SPWeeklySchedule();
                        scheduleWeek.BeginDayOfWeek = DayOfWeek.Sunday;
                        scheduleWeek.BeginHour = hour;
                        scheduleWeek.BeginMinute = minute;
                        scheduleWeek.BeginSecond = 0;
                        scheduleWeek.EndDayOfWeek = DayOfWeek.Sunday;
                        scheduleWeek.EndHour = (scheduleWeek.BeginHour + 1);
                        scheduleWeek.EndMinute = 0;
                        scheduleWeek.EndSecond = 0;
                        indexJob.Schedule = scheduleWeek;
                        break;
                    case "hour":
                        SPHourlySchedule scheduleHour = new SPHourlySchedule();
                        scheduleHour.BeginMinute = minute;
                        indexJob.Schedule = scheduleHour;
                        break;
                }

                indexJob.Update();
                indexJob.Provision();
            //}
        }

        //private bool ValidateProperties(SPFeatureReceiverProperties properties)
        //{
        //    int hour = -1;
        //    int min = -1;
        //    foreach (SPFeatureProperty prop in properties.Feature.Properties)
        //    {
        //        if (string.Compare(prop.Name, SCHEDULESETTING, true) == 0)
        //        {
        //            if (string.IsNullOrEmpty(prop.Value))
        //            {
        //                throw new Exception(string.Format("Feature property {0} cannot be empty.", BEGINHOURSETTING));
        //            }
        //            if (!int.TryParse(prop.Value, out hour))
        //            {
        //                throw new Exception(string.Format("Feature property {0} does not have a valid value ({1}).", BEGINHOURSETTING, prop.Value));
        //            }
        //        }
        //        if (string.Compare(prop.Name, BEGINMINUTESETTING, true) == 0)
        //        {
        //            if (string.IsNullOrEmpty(prop.Value))
        //            {
        //                throw new Exception(string.Format("Feature property {0} cannot be empty.", BEGINMINUTESETTING));
        //            }
        //            if (!int.TryParse(prop.Value, out min))
        //            {
        //                throw new Exception(string.Format("Feature property {0} does not have a valid value ({1}).", BEGINMINUTESETTING, prop.Value));
        //            }
        //        }
        //    }
        //    if (hour == -1)
        //    {
        //        throw new Exception(string.Format("Feature property {0} not found.", BEGINHOURSETTING));
        //    }
        //    if (min == -1)
        //    {
        //        throw new Exception(string.Format("Feature property {0} not found.", BEGINMINUTESETTING));
        //    }
        //    return true;
        //}


        /// <summary>
        /// Occurs when a Feature is deactivated.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;

            // delete the job
            foreach (SPJobDefinition job in webApplication.JobDefinitions)
            {
                if (job.Name == INDEXERJOB_FEATURE_ID)
                    job.Delete();
            }
        }
    }
    
}
